﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using MetaSharp.Transformation.Properties;
using System.Globalization;
using System.Collections;
using NSubstitute;
using Xunit.Extensions;
using System.Threading.Tasks;

namespace MetaSharp.Transformation.Tests.Patterns
{
	public class ExactQuantityTests
	{
        [Fact]
		public void NegativeMatchesIsNotAllowed()
		{
            var p = Pattern.ExactQuantity(Pattern.Any(), -1);
            Pattern.Match(p, "").WaitForThrow< ArgumentOutOfRangeException>();
		}

        [Theory]
        [InlineData("")]
        [InlineData("abc")]
		public async Task ZeroMatchesSucceeds(string input)
		{
            var p = Pattern.ExactQuantity(Pattern.Any(), 0);
            var m = await Pattern.Match(p, input);
            Assert.True(m.Matched);
		}

        [Theory]
        [InlineData("a")]
        [InlineData("ab")]
		public async Task SingleMatchSucceeds(string input)
		{
            var p = Pattern.ExactQuantity(Pattern.Any(), 1);
            var m = await Pattern.Match(p, input);
            Assert.True(m.Matched);
		}

        [Fact]
		public async Task MatchesNElementsSuccessfully()
        {
            var p = Pattern.ExactQuantity(Pattern.Any(), 5);
            var m = await Pattern.Match(p, "abcde");
            Assert.True(m.Matched);
		}

        [Fact]
		public async Task MatchesAndReadsToCorrectPosition()
		{
            var p = Pattern.ExactQuantity(Pattern.Any(), 2);
            var m = await Pattern.Match(p, "abc");
            Assert.Equal('c', m.End.Stream.Next().Current);
		}

        [Fact]
		public async Task ExactQuantityLargerThanStreamFails()
        {
            var p = Pattern.ExactQuantity(Pattern.Any(), 2);
            var m = await Pattern.Match(p, "a");
            Assert.False(m.Matched);
		}

        [Theory]
        [InlineData("aaz")]
        [InlineData("aza")]
        [InlineData("azz")]
        [InlineData("zaa")]
        [InlineData("zaz")]
        [InlineData("zza")]
        [InlineData("zzz")]
		public async Task ExactQuantityDoesNotMatchValueFails(string input)
        {
            var p = Pattern.ExactQuantity(Pattern.Value('a'), 3);
            var m = await Pattern.Match(p, input);
            Assert.False(m.Matched);
        }
	}
}
